/*
 * ProcessingScenegraph - http://transmote.com/psg/ is a
 * derivative of Processing - http://processing.org/ 
 * Copyright (C) 2011, Eric Socolofsky
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.transmote.psg;

import com.transmote.psg.events.KeyEvent;
import com.transmote.psg.events.MouseEvent;

import processing.core.PApplet;

/**
 * <p>
 * A PSpriteContainer sits at the top of the Processing Scenegraph display list.
 * All PSprite instances visible on-screen are descendants of a PSpriteContainer.
 * This means that traversal up the display list from a PSprite instance's parent,
 * to its parent, and so on, will ultimately reach the PSpriteContainer.
 * </p><p>
 * {@link #update()} should be called every frame by application code; <tt>update()</tt>
 * then travels down the display list, from PSprite to PSprite, calling {@link PSprite#update(PApplet)}
 * on each, and then {@link PSprite#draw(PApplet)} on each.
 * </p><p>
 * PSpriteContainer acts as the conduit for input events (such as MouseEvents and KeyEvents)
 * between PApplet and application code (PSprite instances).  Input events are dispatched
 * by PApplet and handled by PSpriteContainer, then sent down through the display list.
 * See {@link com.transmote.psg.events.Event} for more detail on the event flow.
 * </p><p>
 * If the developer wishes to eliminate the display list at runtime,
 * call {@link #dispose()}.
 * </p>
 * 
 * @author		Eric Socolofsky
 * @example		DisplayList
 */
public class PSpriteContainer extends PSprite {
	
	/**
	 * The PSpriteContainer to be the top of the display list.
	 * @param 	p	A reference to the PApplet running this Processing sketch.
	 */
	public PSpriteContainer (PApplet p) {
		this.p = p;
		init();
	}
	
	/**
	 * Calls update() on all PSprite children,
	 * then calls draw() on all PSprite children.
	 */
	/*
	 * Note: PSpriteContainer could instead register with PApplet for pre and draw (via registerPre/Draw),
	 * and call PSprite.prerender and PSprite.render from those handlers,
	 * but this design gives developers freedom to update() PSpriteController as desired.
	 */
	public void update () {
		screenX = 0;
		screenY = 0;
		mouseX = p.mouseX;
		mouseY = p.mouseY;
		
		try {
			prerender();
			render(p);
		} catch (Exception e) {
			System.out.println("PSpriteContainer.update Exception:");
			e.printStackTrace();
		}
	}
	
	/**
	 * Frees up this PSpriteContainer, and all child PSprites, for garbage collection.
	 * NOTE: not yet tested, nor verified in a profiler.
	 */
	public void dispose () {
		super.dispose(true);
	}
	
	/**
	 * @exclude
	 * Implementation of PApplet MouseEvent registration.
	 * Developers should not call this method directly.
	 */
	public void mouseEvent (java.awt.event.MouseEvent awtEvent) {
		processDisplayListEvent(new MouseEvent(awtEvent));
	}
	
	/**
	 * @exclude
	 * Implementation of PApplet KeyEvent registration.
	 * Developers should not call this method directly.
	 */
	public void keyEvent (java.awt.event.KeyEvent awtEvent) {
		processDisplayListEvent(new KeyEvent(awtEvent));
	}
	
	private void init () {
		p.registerDispose(this);
		p.registerMouseEvent(this);
		p.registerKeyEvent(this);
	}
}
